package com.blog.security.config;

import com.alibaba.nacos.shaded.com.google.common.base.Function;
import com.blog.security.filter.JwtTokenAuthenticationFilter;
import com.blog.security.handler.CustomAuthenticationEntryPoint;
import com.blog.security.handler.CustomAuthenticationFailureHandler;
import com.blog.security.handler.CustomAuthenticationSuccessHandler;
import com.blog.security.handler.CustomerLogoutSuccessHandler;
import com.blog.security.service.SecurityUserDetailSevice;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.provisioning.UserDetailsManagerResourceFactoryBean;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository;
import reactor.core.publisher.Mono;

import java.util.ArrayList;

/**
 * @ClassName securityConfig
 * @Destription 与springboot一样配置security信息，但略有不同
 * @Author 天堂小野花
 * @Date 2025/8/10  0:00
 * @Version 1.0
 */
@Configuration
@EnableWebFluxSecurity
public class securityConfig {

    private static final String[] excludeAuthPages={"/doLogin"};
    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    // 实现该处的ReactiveUserDetailsService
    @Bean
    public ReactiveAuthenticationManager reactiveAuthenticationManager(SecurityUserDetailSevice userDetailsService, PasswordEncoder passwordEncoder){
        UserDetailsRepositoryReactiveAuthenticationManager authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService);
        authenticationManager.setPasswordEncoder(passwordEncoder);
        return authenticationManager;
    }
    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http,
                                                         CustomAuthenticationEntryPoint customAuthenticationEntryPoint,
                                                         CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler,
                                                         CustomAuthenticationFailureHandler customAuthenticationFailureHandler,
                                                         CustomerLogoutSuccessHandler customerLogoutSuccessHandler,
                                                         JwtProperties jwtProperties,
                                                         ReactiveAuthenticationManager reactiveAuthenticationManager){
        http.csrf(ServerHttpSecurity.CsrfSpec::disable)
                .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
                .authenticationManager(reactiveAuthenticationManager)
                .exceptionHandling()
                .authenticationEntryPoint(customAuthenticationEntryPoint)// 自定义authenticationEntryPoint
                .accessDeniedHandler((swe,e)->{
                    swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                    return swe.getResponse().writeWith(Mono.just(new DefaultDataBufferFactory().wrap("FORBIDDEN".getBytes())));
                })
                .and()
                .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
                .authorizeExchange()
                .pathMatchers(excludeAuthPages).permitAll() // 白名单
                .pathMatchers(HttpMethod.OPTIONS).permitAll() //OPTIONS请求默认放行
                .anyExchange()
                .authenticated()
                .and()
                .formLogin().loginPage("/plateform/doLogin")
                .authenticationSuccessHandler(customAuthenticationSuccessHandler)// 自定义authenticationSuccessHandler
                .authenticationFailureHandler(customAuthenticationFailureHandler) // 自定义authenticationFailureHandler
                .and()
                .logout().logoutUrl("/plateform/logout")
                .logoutSuccessHandler(customerLogoutSuccessHandler)//  自定义logoutSuccessHandler
                .and()
                .addFilterAt(new JwtTokenAuthenticationFilter(jwtProperties), SecurityWebFiltersOrder.HTTP_BASIC) //  增加tokenFilter
                 ;
        return http.build();
    }
}
